home *** CD-ROM | disk | FTP | other *** search
/ MACD 5 / MACD 5.bin / workbench / libs / newlooklib.lha / newlook / smartmem.c < prev    next >
C/C++ Source or Header  |  1993-12-26  |  14KB  |  678 lines

  1. /*
  2.  *  SMARTMEM.C
  3.  *
  4.  *  (c)Copyright 1991-93 by Tobias Ferber,  All Rights Reserved.
  5.  */
  6.  
  7. #include <stdlib.h>
  8.  
  9. #include <exec/types.h>
  10. #include <exec/memory.h>
  11.  
  12. /* exec.library prototypes */
  13. extern void *AllocMem(ULONG,ULONG);
  14. extern void FreeMem(void *,ULONG);
  15.  
  16. #include "newlook.h"
  17.  
  18. /*
  19.  *  --- PRIVATE ---
  20.  */
  21.  
  22. /****i* newlook.lib/--background-- ******************************************
  23. *
  24. *   SMARTMEM
  25. *    smartmem.o offers some very useful functions concering
  26. *    memory management on Amiga systems.
  27. *    ... bla, bla, bla ...
  28. *
  29. *   IDEAS
  30. *    SmartAllocRaster()
  31. *    SmartAllocMem(<bytesize>,<memory-type>)
  32. *
  33. *    typedef struct memnode {
  34. *
  35. *      struct memnode *succ,*pred;
  36. *      ULONG handle;
  37. *
  38. *      union {
  39. *        APTR memory;
  40. *        PLANEPTR plane;
  41. *      } ptr;
  42. *
  43. *      union {
  44. *        ULONG bytesize;
  45. *        struct {
  46. *          USHORT width,
  47. *                 height;
  48. *        } dimen;
  49. *      } size;
  50. *
  51. *      enum { RASTER,MEMORY } type;  /* memtype attributes */
  52. *    } memnode_t;
  53. *
  54. ******************************************************************************
  55. *
  56. */
  57.  
  58. typedef struct memnode {
  59.  
  60.   struct memnode *succ,
  61.                  *pred;
  62.   ULONG handle;
  63.   void *memory;
  64.   ULONG bytesize;
  65.  
  66. } memnode_t;
  67.  
  68. #define NIL(type) (type)0L
  69. static memnode_t *memlist= NIL(memnode_t *);
  70. static ULONG current_handle= 0L;
  71.  
  72. /****i* newlook.lib/tail ******************************************
  73. *
  74. *   NAME
  75. *    tail -- Return the last memnode pointer in a list
  76. *
  77. *   SYNOPSIS
  78. *    t = tail( n )
  79. *
  80. *    memnode_t *tail( memnode_t * );
  81. *
  82. *   FUNCTION
  83. *    Traverse the list of memnodes linked to n->succ until
  84. *    n->succ is == NIL(menode_t *).
  85. *
  86. *   INPUTS
  87. *    n - pointer to any memnode or NIL(memnode_t *)
  88. *
  89. *   RESULT
  90. *    t - the last memnode or NIL(memnode_t *) if n was NIL(memnode_t *)
  91. *
  92. *   SEE ALSO
  93. *    head()
  94. *
  95. ******************************************************************************
  96. *
  97. */
  98.  
  99. static memnode_t *tail(memnode_t *n)
  100. {
  101.   return (n && n->succ) ? tail(n->succ) : n;
  102. }
  103.  
  104.  
  105. /****i* newlook.lib/head ******************************************
  106. *
  107. *   NAME
  108. *    head -- Return the first memnode pointer in a list
  109. *
  110. *   SYNOPSIS
  111. *    t = head( n )
  112. *
  113. *    memnode_t *head( memnode_t * );
  114. *
  115. *   FUNCTION
  116. *    Traverse the list of memnodes linked to n->pred until
  117. *    n->pred is == NIL(menode_t *).
  118. *
  119. *   INPUTS
  120. *    n - pointer to any memnode or NIL(memnode_t *)
  121. *
  122. *   RESULT
  123. *    t - the last memnode or NIL(memnode_t *) if n was NIL(memnode_t *)
  124. *
  125. *   SEE ALSO
  126. *    tail()
  127. *
  128. ******************************************************************************
  129. *
  130. */
  131.  
  132. static memnode_t *head(memnode_t *n)
  133. {
  134.   return (n && n->pred) ? head(n->pred) : n;
  135. }
  136.  
  137.  
  138. /****i* newlook.lib/addnode ******************************************
  139. *
  140. *   NAME
  141. *    addnode -- Add a (list of) memnode(s) to the head of memlist
  142. *
  143. *   SYNOPSIS
  144. *    addnode( n )
  145. *
  146. *    void addnode( memnode_t * );
  147. *
  148. *   FUNCTION
  149. *    Add memlist to the tail of n and make n the head of the new memlist
  150. *
  151. *   INPUTS
  152. *    n - pointer to any memnode or NIL(memnode_t *)
  153. *
  154. *   RESULT
  155. *    None.
  156. *
  157. *   NOTES
  158. *    calling addnode( NIL(memnode_t *) ) is a no-op.
  159. *
  160. *   SEE ALSO
  161. *    new()
  162. *
  163. ******************************************************************************
  164. *
  165. */
  166.  
  167. static void addnode(memnode_t *n)
  168. {
  169.   register memnode_t *t;
  170.  
  171.   if(t= tail(n))
  172.   {
  173.     if( t->succ= head(memlist) )
  174.       t->succ->pred= t;
  175.  
  176.     memlist= head(n);
  177.   }
  178. }
  179.  
  180.  
  181. /****i* newlook.lib/new ******************************************
  182. *
  183. *   NAME
  184. *    new -- Allocate and initialize a new memnode
  185. *
  186. *   SYNOPSIS
  187. *    n= new()
  188. *
  189. *    memnode_t *new( void );
  190. *
  191. *   FUNCTION
  192. *    Allocate a new memnode using malloc() and initialize it.
  193. *    Especially the current handle will be copied to n->handle.
  194. *
  195. *   INPUTS
  196. *    None.
  197. *
  198. *   RESULT
  199. *    n - pointer to the new memnode or NIL(memnode_t *) on error.
  200. *
  201. *   NOTES
  202. *    calling new() will not automatically chain the the new memnode
  203. *
  204. *   SEE ALSO
  205. *    addnode()
  206. *
  207. ******************************************************************************
  208. *
  209. */
  210.  
  211. static memnode_t *new(void)
  212. {
  213.   register memnode_t *n;
  214.  
  215.   if(n= (memnode_t *)malloc(sizeof(memnode_t)))
  216.   {
  217.     n->succ=
  218.     n->pred= NIL(memnode_t *);
  219.  
  220.     n->handle= current_handle;
  221.  
  222.     n->memory= NIL(void *);
  223.     n->bytesize= 0UL;
  224.   }
  225.   return n;
  226. }
  227.  
  228.  
  229. /****i* newlook.lib/dispose ******************************************
  230. *
  231. *   NAME
  232. *    dispose -- Unchain a memnode from memlist and free it
  233. *
  234. *   SYNOPSIS
  235. *    dispose( n );
  236. *
  237. *    void dispose( memnode_t * );
  238. *
  239. *   FUNCTION
  240. *    Unchain n and keep memlist sane.
  241. *
  242. *   INPUTS
  243. *    n - pointer to the memnode which is about to be disposed
  244. *
  245. *   RESULT
  246. *    None.
  247. *
  248. *   NOTES
  249. *    n->memory is _NOT_ freed by this function!
  250. *    If n is the last node in memlist then memlist is set to NIL.
  251. *
  252. *   SEE ALSO
  253. *    new(), addnode()
  254. *
  255. ******************************************************************************
  256. *
  257. */
  258.  
  259. static void dispose(memnode_t *n)
  260. {
  261.   if(n->pred == n->succ)
  262.   { /* hacky: they _must_ be both NIL to be equal... */
  263.     memlist= NIL(memnode_t *);
  264.   }
  265.   else
  266.   {
  267.     if(n == memlist)
  268.     {
  269.       if(n->pred)
  270.         memlist= head(n->pred);  /* should not happen */
  271.       else
  272.         memlist= n->succ;
  273.     }
  274.  
  275.     if(n->pred)
  276.       n->pred->succ= n->succ;
  277.  
  278.     if(n->succ)
  279.       n->succ->pred= n->pred;
  280.  
  281.     n->pred=
  282.     n->succ= NIL(memnode_t *);
  283.   }
  284.   free(n);
  285. }
  286.  
  287.  
  288. /****i* newlook.lib/findnode ******************************************
  289. *
  290. *   NAME
  291. *    findnode -- Find a memnode with memory at a certain location
  292. *
  293. *   SYNOPSIS
  294. *    n = findnode( mem );
  295. *
  296. *    memnode_t *findnode( void * );
  297. *
  298. *   FUNCTION
  299. *    Scan memlist for a memnode which has memory allocated at given
  300. *    location "mem" with the current memory management handle.
  301. *
  302. *   INPUTS
  303. *    mem   - pointer to the memory returned by SmartAllocMem()
  304. *        or the macro SmartAllocate()
  305. *
  306. *   RESULT
  307. *    n     - the memnode with n->memory equal to mem and n->handle
  308. *        equal to the current_handle.
  309. *
  310. *   SEE ALSO
  311. *    addnode()
  312. *
  313. ******************************************************************************
  314. *
  315. */
  316.  
  317. static memnode_t *findnode(void *mem)
  318. {
  319.   register memnode_t *n= head(memlist);
  320.  
  321.   /*for(n= head(memlist); n && n->memory != mem; n= n->succ) ;*/
  322.  
  323.   while(n && n->memory != mem)
  324.     n= n->succ;
  325.  
  326.   return (n && n->handle == current_handle) ? n : NIL(memnode_t *);
  327. }
  328.  
  329.  
  330. /*
  331.  *  --- PUBLIC ---
  332.  */
  333.  
  334. /****** newlook.lib/SetNewLookHandle ******************************************
  335. *
  336. *   NAME
  337. *    SetNewLookHandle -- Set the current memory management handle
  338. *
  339. *   SYNOPSIS
  340. *    lastHandle = SetNewLookHandle( newHandle )
  341. *
  342. *    ULONG SetNewLookHandle( ULONG );
  343. *
  344. *   FUNCTION
  345. *    Set the current memory management handle to newHandle and return
  346. *    the last handle.
  347. *
  348. *   INPUTS
  349. *    newHandle  - a unique number > 0 to identify your memory.
  350. *
  351. *   RESULT
  352. *    lastHandle - the last handle.
  353. *
  354. *   NOTES
  355. *    There are some reserved handles such as PRIVATE_HANDLE or
  356. *    MAGIC_HANDLE which you must not use here!
  357. *
  358. *   SEE ALSO
  359. *    MakePrivateHandlePublic()
  360. *
  361. ******************************************************************************
  362. *
  363. */
  364.  
  365. ULONG SetNewLookHandle(ULONG new_handle)
  366. {
  367.   register ULONG last_handle= current_handle;
  368.   current_handle= new_handle;
  369.   return last_handle;
  370. }
  371.  
  372.  
  373. /****** newlook.lib/SmartAllocMem ******************************************
  374. *
  375. *   NAME
  376. *    SmartAllocMem -- Allocate and remember memory for a handle
  377. *
  378. *   SYNOPSIS
  379. *    mem = SmartAllocMem( numbytes, attributes )
  380. *
  381. *    void *SmartAllocMem( ULONG, ULONG );
  382. *
  383. *   FUNCTION
  384. *    Allocate system memory via AllocMem() and chain it to the
  385. *    newlook memlist using the current memory management handle.
  386. *
  387. *   INPUTS
  388. *    numbytes      - The size of the desired block in bytes. (The
  389. *            operating system will automatically round this
  390. *            number to a multiple of the system memory chunk
  391. *            size.)
  392. *    attributes    - requirements as explained in exec.library autodoc
  393. *            file and/or exec/memory.h
  394. *
  395. *   RESULT
  396. *    mem - a pointer to the newly allocated memory block.
  397. *        If there are no free memory regions large enough to satisfy
  398. *        the request, zero will be returned.  The pointer must be
  399. *        checked for zero before the memory block may be used!
  400. *        The memory block returned is long word aligned.
  401. *
  402. *   SEE ALSO
  403. *    SetNewLookHandle(), SmartAllocate(), SmartFree(), SmartFreeAll()
  404. *    exec.library/AllocMem()
  405. *
  406. ******************************************************************************
  407. *
  408. */
  409.  
  410. void *SmartAllocMem(ULONG numbytes, ULONG attributes)
  411. {
  412.   register memnode_t *n;
  413.   register void *mem= NIL(void *);
  414.  
  415.   if(n= new())
  416.   {
  417.     if(mem= (void *)AllocMem(numbytes, attributes))
  418.     {
  419.       n->memory= mem;
  420.       n->bytesize= numbytes;
  421.       addnode(n);
  422.     }
  423.     else dispose(n);
  424.   }
  425.   return mem;
  426. }
  427.  
  428.  
  429. #ifdef OBSOLETE
  430.  
  431. /****** newlook.lib/SmartRemember ******************************************
  432. *
  433. *   NAME
  434. *    SmartRemember -- Remember manually allocated memory (obsolete)
  435. *
  436. *   SYNOPSIS
  437. *    success = SmartRemember( mem, numbytes )
  438. *
  439. *    int SmartRemember( void *, ULONG );
  440. *
  441. *   FUNCTION
  442. *    Chain given memory block "mem" to the newlook memlist using
  443. *    the current memory management handle.
  444. *
  445. *   INPUTS
  446. *    mem           - pointer to a memory block which has been
  447. *            allocated via AllocMem()
  448. *    numbytes      - the size of the allocated memory block in
  449. *            bytes.
  450. *
  451. *   RESULT
  452. *    success - 1 on success, 0 on error
  453. *
  454. *   NOTES
  455. *    This function is declared obsolete and will be removed!
  456. *
  457. *   SEE ALSO
  458. *    SmartAllocMem(), exec.library/AllocMem()
  459. *
  460. ******************************************************************************
  461. *
  462. */
  463.  
  464. int SmartRemember(void *mem, ULONG numbytes)
  465. {
  466.   register memnode_t *n= NIL(memnode_t *);
  467.  
  468.   if(mem && numbytes)
  469.   {
  470.     if(n= new())
  471.     {
  472.       n->memory= mem;
  473.       n->bytesize= numbytes;
  474.       addnode(n);
  475.     }
  476.   }
  477.   return n ? 1:0;
  478. }
  479. #endif /* OBSOLETE */
  480.  
  481.  
  482. /****** newlook.lib/SmartFree ******************************************
  483. *
  484. *   NAME
  485. *    SmartFree -- Free memory allocated via SmartAllocMem()
  486. *
  487. *   SYNOPSIS
  488. *    nil = SmartFree( mem )
  489. *
  490. *    void *SmartFree( void * );
  491. *
  492. *   FUNCTION
  493. *    Free the memory block allocated via SmartAllocMem() and
  494. *    the current memory management handle.
  495. *
  496. *   INPUTS
  497. *    mem - pointer to the memory block returned by SmartAllocMem()
  498. *
  499. *   RESULT
  500. *    nil - a constant pointer to NIL(void *)
  501. *
  502. *   NOTES
  503. *    If given pointer "mem" has never been returned by SmartAllocMem()
  504. *    or if it has already been freed up then calling this function is
  505. *    a no-op.
  506. *
  507. *   SEE ALSO
  508. *    SmartAllocMem(), SmartFreeAll()
  509. *
  510. ******************************************************************************
  511. *
  512. */
  513.  
  514. void *SmartFree(void *mem)
  515. {
  516.   register memnode_t *n;
  517.  
  518.   if( n= findnode(mem) )
  519.   {
  520.     if(n->memory && n->bytesize)
  521.       FreeMem(mem,n->bytesize);
  522.  
  523.     dispose(n);
  524.   }
  525.   return NIL(void *);
  526. }
  527.  
  528.  
  529. /****** newlook.lib/SmartFreeAll ******************************************
  530. *
  531. *   NAME
  532. *    SmartFreeAll -- Free all memory allocated for a certain handle
  533. *
  534. *   SYNOPSIS
  535. *    nil = SmartFreeAll( handle )
  536. *
  537. *    void *SmartFreeAll( ULONG );
  538. *
  539. *   FUNCTION
  540. *    Free all the memory which has been allocated via SmartAllocMem()
  541. *    for the given newlook handle.
  542. *
  543. *   INPUTS
  544. *    handle - the handle to be freed or MAGIC_HANDLE for all handles
  545. *
  546. *   RESULT
  547. *    nil - a constant pointer to NIL(void *)
  548. *
  549. *   NOTES
  550. *    Calling SmartFreeAll( MAGIC_HANDLE ) will free all memory ever
  551. *    chained to the memlist.
  552. *
  553. *   SEE ALSO
  554. *    SmartFree(), SmartAllocMem()
  555. *
  556. ******************************************************************************
  557. *
  558. */
  559.  
  560. void *SmartFreeAll(ULONG handle)
  561. {
  562.   register memnode_t *n= head(memlist);
  563.  
  564.   while(n)
  565.   {
  566.     register memnode_t *t= n;
  567.     n= n->succ;
  568.  
  569.     if(t->handle == handle || handle == MAGIC_HANDLE)
  570.     {
  571.       if(t->memory && t->bytesize)
  572.         FreeMem(t->memory, t->bytesize);
  573.  
  574.       dispose(t);
  575.     }
  576.   }
  577.   return NIL(void *);
  578. }
  579.  
  580.  
  581. #ifdef DEBUG
  582.  
  583. /****** newlook.lib/DebugSmartMemList ******************************************
  584. *
  585. *   NAME
  586. *    DebugSmartMemList -- Print all memnodes in memlist
  587. *
  588. *   SYNOPSIS
  589. *    DebugSmartMemList()
  590. *
  591. *    void DebugSmartMemList( void );
  592. *
  593. *   FUNCTION
  594. *    Traverse the memlist and print information about all nodes chained
  595. *    to it.
  596. *
  597. *   NOTES
  598. *    This function is only available when comiled w/ -DDEBUG !
  599. *
  600. ******************************************************************************
  601. *
  602. */
  603.  
  604. void DebugSmartMemList(void)
  605. {
  606.   register memnode_t *n= head(memlist);
  607.  
  608.   if(n)
  609.   {
  610.     printf("  Handle  |  Memory  |  Bytesize\n"
  611.            "----------+----------+------------\n");
  612.  
  613.     while(n)
  614.     {
  615.       printf("%9ld | 0x%06lX | %ld\n",n->handle,n->memory,n->bytesize);
  616.       n= n->succ;
  617.     }
  618.   }
  619.   else printf("%s: Memory list is empty.\n",__FILE__);
  620. }
  621. #endif /* DEBUG */
  622.  
  623.  
  624. /*
  625.  *  --- NewLook PRIVATE ---
  626.  */
  627.  
  628. /****** newlook.lib/MakePrivateHandlePublic ******************************************
  629. *
  630. *   NAME
  631. *    MakePrivateHandlePublic -- change memory handle from private to public
  632. *
  633. *   SYNOPSIS
  634. *    MakePrivateHandlePublic( publicHandle )
  635. *
  636. *    void MakePrivateHandlePublic( ULONG );
  637. *
  638. *   FUNCTION
  639. *    Traverse the memlist and change all memnodes with a memory block
  640. *    allocated with the PRIVATE_HANDLE to the given publicHandle.
  641. *
  642. *   INPUTS
  643. *    publicHandle  - The new handle for the private memnodes.
  644. *
  645. *   RESULT
  646. *    None.
  647. *
  648. *   EXAMPLE
  649. *    Federal regulations prohibit a demonstration of this function.
  650. *
  651. *   NOTES
  652. *    This function is newlook private and should not be called by the
  653. *    user!
  654. *
  655. *   SEE ALSO
  656. *    SetNewLookHandle(), SmartAllocMem()
  657. *
  658. ******************************************************************************
  659. *
  660. */
  661.  
  662. void MakePrivateHandlePublic(ULONG public_handle)
  663. {
  664.   if(public_handle != PRIVATE_HANDLE)
  665.   {
  666.     register memnode_t *n= head(memlist);
  667.  
  668.     while(n)
  669.     {
  670.       if(n->handle == PRIVATE_HANDLE)
  671.         n->handle= public_handle;
  672.  
  673.       n= n->succ;
  674.     }
  675.   }
  676.   current_handle= public_handle;
  677. }
  678.